/*
 * @Author: wangzy
 * @Date: 2022-06-20 09:55:32
 * @LastEditors: wangzy
 * @LastEditTime: 2022-06-21 20:55:06
 * @Description:
 */
let p1 = new Promise((resolve, reject) => {
  resolve('成功')
  reject('失败')
})
// console.log('p1', p1)
let p2 = new Promise((resolve, reject) => {
  // reject('失败')
  resolve('成功')
})
// console.log('p2', p2)
/**
 * 1、执行了resolve，Promise状态会变成fulfilled
 * 2、执行了reject，Promise状态会变成rejected
 * 3、Promise只以第一次为准，第一次成功就永久为fulfilled，第一次失败就永远状态为rejected
 * 4、Promise中有throw的话，就相当于执行了reject
 */

//1、实现resolve与reject
// Promise的初始状态是 pending
// 这里很重要的一步是 resolve和reject的绑定this，为什么要绑定this呢？这是 为了 resolve和reject的this指向 永远指向当前的 MyPromise实例
// 防止随着函数执行环境的改变而改变

class MyPromise {
  // 构造方法
  constructor(executor) {
    // 初始化值
    this.initValue()
    //  初始化this指向
    this.initBind()

    // 执行传进来的函数
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }

  initBind() {
    // 初始化this
    this.resolve = this.resolve.bind(this)
    this.reject = this.reject.bind(this)
  }

  initValue() {
    // 初始化值
    this.PromiseState = 'pending'
    this.PromiseResult = null
    this.onFulfilledCallbacks = [] // 保存成功回调
    this.onRejectedCallbacks = [] // 保存失败回调
  }

  resolve(value) {
    // state是不可变的
    // debugger
    if (this.PromiseState !== 'pending') return
    // 如果执行resolve，状态变为fulfilled
    this.PromiseState = 'fulfilled'
    // 终值为传进来的值
    this.PromiseResult = value

    while (this.onFulfilledCallbacks.length) {
      //  取出 onFulfilledCallbacks 第一个 并执行，利用shift的特点删除数组的第一个元素，并返回删除的元素。
      this.onFulfilledCallbacks.shift()(this.PromiseResult)
    }
  }
  reject(reson) {
    // state是不可变的
    if (this.PromiseState !== 'pending') return
    // 如果执行reject，状态变为rejected
    this.PromiseState = 'rejected'
    // 终值为传进来的reason
    this.PromiseResult = reson
    while (this.onFulfilledCallbacks.length) {
      //  取出 onRejectedCallbacks 第一个 并执行，利用shift的特点删除数组的第一个元素，并返回删除的元素。
      this.onRejectedCallbacks.shift()(this.PromiseResult)
    }
  }
  // then
  /**
   * 1. then接收两个回调，一个是成功回调，一个是失败回调
   * 2. 当Promise状态未fulfilled 执行成功回调，为 rejected 执行失败回调
   * 3. 如 resolve或 reject在定时器里，则定时器结束后在执行then
   * 4. then支持 链式调用，下一次then执行受上一次then返回值的影响
   */
  then(onFulfilled, onRejected) {
    // 接收两个回调 onFulfilled, onRejected
    // 参数校验，确保一定是函数
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (val) => val
    onRejected =
      typeof onRejected === 'function'
        ? onRejected
        : (reason) => {
            throw reason
          }

    if (this.PromiseState === 'fulfilled') {
      // 如果当前为成功状态，执行第一个回调
      onFulfilled(this.PromiseResult)
    } else if (this.PromiseState === 'rejected') {
      // 如果当前为失败状态，执行第二个回调
      onRejected(this.PromiseResult)
    } else if (this.PromiseState === 'pending') {
      // 如果状态为待定状态，暂时保存两个回调
      console.log(onFulfilled)
      this.onFulfilledCallbacks.push(onFulfilled.bind(this))
      this.onRejectedCallbacks.push(onRejected.bind(this))
    }
  }
}
// 测试一下
const testp1 = new MyPromise((resolve, reject) => {
  resolve('成功')
  reject('失败')
})
console.log('testp1', testp1)
const testp2 = new MyPromise((resolve, reject) => {
  reject('失败')
})

// 报错 走reject
console.log('testp2', testp2)
const testp3 = new MyPromise((resolve, reject) => {
  throw '报错失败'
})
console.log('testp3', testp3)

// then
const testp4 = new MyPromise((resolve, reject) => {
  resolve('成功')
}).then(
  (res) => console.log('testp4', res),
  (err) => console.log('testp4', err)
)
const testp5 = new MyPromise((resolve, reject) => {
  reject('失败')
}).then(
  (res) => console.log('testp5'.res),
  (err) => console.log('testp5', err)
)

//  上面已经实现.then 最基本的功能 那么如果是定时器情况呢？ 怎么才能保证在1m后在执行then里面的回调
const testp6 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    let data = {
      code: 1,
      data: {
        name: 'wzy',
      },
    }
    resolve(data)
  }, 4000)
})
  .then((res) => {
    console.log('testp6', res)
  })
  .then((res) => {
    console.log(res)
  })
